数据结构和算法的优化
数据结构是为了更合理的使用计算机的
内存。并且适台计算机的寻址方式,使
中央处理器更有效的寻址。在CPU寻址时一般使用32/64位的地址,一次防问的内存单元一般是四个或八十字节.所以设计数据结构时要考虑计算机的字节对齐.这样可提高读取的速度。由于平台不同,不同数据类型存储字节不同,结构中数据类型的排列顺序不同。占有的内存容量就不同.所以设计数据结构时,要考虑平台的存储分配。如比特域,既有内存影响,又有性能影响。内存影响与结构中相似,在windows平台下比特域占4字节,合理使用这4个字节.可以充分利用内存。同时变量的集中存放,可以生成速度快的代码.
程序的高效算法可以说是软件效率的必要条件。但它不是性能的必要条件.性能是几个必要因素的综合结果。
编码的效率
语言结构
每个语言在其中增加了功能和灵活性。这些优点不是无偿的。指针是 c 语言中的一个特色,功能强大,但也是出错的根源。它虽然很灵活,可以操作内存,但是由于本身没有对指针进行边界检测,所以常导致缓冲区溢出的漏洞, 但指针的效率是比较高的。在访问数组时, 指针访问速度比直接用数组下标要快,因为数组访问时每次计算下标后从数组头开始访问数组元素,而指针可以根据数据类型直接定位到元素,但有的编译器中数组就比指针快。C 语言中的数字既有无符号也有有符号的,它们可以由编译器作默认的转变,同时不同的数字数据类型之间也是不加提示的提升和截断,这也是出现漏洞和产生错误的根源,在优化时也明确地指明数据类型的转化,既增加了可读性也减少了出错的几率。所以要根据实际的需要来使用数据类型,不要使用过长的数据类型,增加不必要的计算周期,尤其在能使用整数时不要使用浮点数。在作乘除或求余时, 可以转化为位运算。还有 + = ,++运算符,虽然+=和一般的加法赋值结果一样, 但是 + = 运算少了一次的读操作。+ +有前缀和后缀之分,但是前缀 ++ 操作少了临时变量的生成, 效率上也高。
系统体系结构
系统体系结构是指影响性能的受计算机硬件结构限制的,包括内存容量的限制,存储开销不均衡以及在普通的计算机上并不能实现真正的并行。CPU 都采用流水线指令处理且存储开销的不平衡,所以循环展开和利用缓存是提高性能的关键。
循环展开和多路就是充分利用系统的体系结构来提高性能的,尤其在数组存取上,当在循环中存取一维数组时或作数组的运算时,在每次循环中,把逻辑上独立的数组的运算分成多次,既利用了CPU 的流水线指令处理特征,提高了并行性,又减少了循环次数。不过由于
CPU的寄存器数量的限制,循环多路最多四次,如果次数过多,反而性能下降,因为寄存器不足以存放循环中的值,需要放到栈中,这样就降低了性能,即所谓的寄存器溢出。
缓存是另外的一种提高性能的方式,在多维数组的存取时,既要考虑平台存储多维数组的方式,又要考虑程序的局部性,防止缓存每次存取的不命中。
系统库
在设计系统库时,通常运用灵活性和通用性的思想,但是灵活性和通用性以及性能之间存在一个平衡.所以说库在某些情况下也并不是最优化的。例如标准库性能很高效的,由于其通用性,在某些情况下,没有充分利用条件参数,导致程序逻辑的执行很多是无用的,效率上也不是最好的,这时用自己的函数来替代系统库使效率最优。再者由于库函数对系统的资源分配和程序的安全性等要求也不一样,程序的效率也不相同。如函数puts()就比其他的输出函数要快。一些系统库提供的容器,它们使用不同的数据结构来分配空间,效率也相差很大。还有一些文件读取函数,因为使用的读取块大小不同以及使用不使用缓冲而有很大的效率差别。
编译器的优化
编译器的优化包括循环的展开,把常量表达式放到循环之外以及消除多余计算的技术。大多数的编译器会完成这样的优化。但不要指望任何特定的编译器完成特定的优化。有的编译器循环展开 2 次,而有的展开 4次, 还有一些根本不展开。为了最终控制权必须把编码问题掌握在自己手中。